package dbCore

import (
	"errors"
	"fmt"
)

func (db *Db) Set(key, value []byte) error {

	// TODO 检查数据是否有效

	db.mu.Lock()
	defer db.mu.Unlock()

	entry := NewEntry(key, value, nil, String, StringSet)
	// 将entry存在db中
	if err := db.store(entry); err != nil {
		return err
	}

	// 数据索引
	idx := &Index{
		Meta: &Meta{
			Key:     entry.Meta.Key,
			KeySize: uint32(len(entry.Meta.Key)),
		},
		FileId:    db.activateFileId,
		EntrySize: entry.Size(),
		Offset:    db.activateFile.Offset - int64(entry.Size()), // 因为在store函数中，Offset加上了entry大小了
	}

	// 构建索引
	if err := db.buildIndex(entry, idx); err != nil {
		return err
	}

	// TODO 清除过期时间
	return nil
}

func (db *Db) Get(key []byte) ([]byte, error) {
	keySize := len(key)
	if keySize == 0 {
		return nil, errors.New("key为空")
	}
	element := db.strIdxList.Get(key)
	if element == nil {
		return nil, errors.New("没有该key")
	}
	element_value := element.ElementGetValue().(*Index)
	if element_value == nil {
		return nil, errors.New("该key没有值")
	}
	db.mu.Lock()
	defer db.mu.Unlock()

	// TODO 判断是否过期

	// 如果key和value都在内存中，则直接去内存中读取
	if db.config.IdxMode == 0 {
		return element_value.Meta.Value, nil
	} else {
		fmt.Println("else")
	}
	return nil, errors.New("其他错误")
}

func (db *Db) SetNx(key, value []byte) error {
	if exist := db.Existed(key); exist {
		return errors.New("已经存在")
	}
	return db.Set(key, value)
}

func (db *Db) Existed(key []byte) bool {
	db.mu.Lock()
	defer db.mu.Unlock()
	exist := db.strIdxList.Exist(key)
	// TODO 还要检测是否过期
	if exist {
		return true
	}
	return false
}

func (db *Db) GetSet(key, val []byte) (before []byte, err error) {
	before, _ = db.Get(key)
	err = db.Set(key, val)
	return
}

func (db *Db) Append(key, val []byte) error {
	before_value, _ := db.Get(key)
	// TODO 过期时间
	var after_value []byte
	if before_value != nil {
		after_value = append(before_value, val...)
	} else {
		after_value = val
	}
	if err := db.Set(key, after_value); err != nil {
		return err
	}
	return nil
}

func (db *Db) Strlen(key []byte) (res int, err error) {
	db.mu.Lock()
	defer db.mu.Unlock()
	// TODO 过期时间
	value := db.strIdxList.Get(key)
	if value != nil {
		r := value.Value().(*Index)
		res = int(r.Meta.ValueSize)
		err = nil
		return
	}
	return 0, errors.New("长度为0")
}
